import clutter
import cluttergtk
import gobject
import gtk
import os
import filepicker
import threading
from gtk.gdk import threads_enter, threads_leave

button = gtk.Button()

RETRY_OK = 1
RETRY_CANCEL = 2
RETRY_LATER = 3

#class BehaviourBounce(clutter.Behaviour):
#    
#    __gtype_name__ = 'BehaviourBounce'
#    
#    def __init__(self, alpha=None):
#        clutter.Behaviour.__init__(self)
#        self.set_alpha(alpha)
#        self.move_length = 40;
#    
#    def do_alpha_notify(self, alpha_value):
#        pos = self.move_length * alpha_value / clutter.MAX_ALPHA
#        for actor in self.get_actors():
#            actor.set_position(pos, actor.get_y())
#
#
#class AppUi:
#    
#    def start(self):
#        stage_color = clutter.Color(0x99, 0xcc, 0xff, 0xff)
#    
#        stage = clutter.Stage()
#        #stage.connect('button-press-event', clutter.main_quit)
#        stage.connect('destroy', clutter.main_quit)
#        stage.set_color(stage_color)
#
#        # need a gtk object for getting access, otherwise we get shouted at
#        # by clutter
#        
#        picker = filepicker.FilePicker()
#        stage.add(picker)
#        
#        picker.show()
#        stage.show()
#        clutter.main()
#        
#    def create_test_icon(self):
#        texture = cluttergtk.Texture()
#        texture.set_from_icon_name(button, 'folder_home', -1)
#        return texture
#
#class IconButton(clutter.Group):
#    
#    __gsignals__ = {
#        'clicked' : ( \
#          gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () \
#        ),
#        'mouse-over' : ( \
#          gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () \
#        ),
#    }
#    
#    def __init__(self):
#        clutter.Group.__init__(self)
#        self.set_reactive(True)
#        self.connect('button-release-event', self.do_button_release_event)
#        self.connect('enter-event', self.do_enter_event)
#        self.connect('leave-event', self.do_leave_event)
#        self._label_actor = clutter.Label()
#        self._label = ""
#        self.add(self._label_actor)
#        
#    def set_icon_name(self, name):
#        texture = cluttergtk.Texture()
#        texture.set_from_icon_name(button, name)
#        self.add(texture)
#        
#    def set_label(self, label):
#        self._label = label
#        
#    def do_button_release_event(self, actor, event):
#        self._start_label_tween()
#        self.emit('clicked')
#        
#    def do_enter_event(self, actor, event):
#        self._show_label()
#        
#    def do_leave_event(self, actor, event):
#        pass
#    
#    def _show_label(self):
#        self._label_actor.set_text(self._label)
#        self._label_actor.show()
#        
#    def _start_label_tween(self):
#        timeline = self._timeline = clutter.Timeline(fps=60, duration=1000)
#        timeline.set_loop(False)
#        alpha = self._alpha = clutter.Alpha(timeline, clutter.sine_func)
#        path_b = self._path_b = BehaviourBounce(alpha)
#        path_b.apply(self)
#        
#        timeline.start()

class EncoderProgressMonitor():
    
    def __init__(self):
        threads_enter()
        self._dialog = gtk.Dialog(title='Encoding Progress')
        
        self._progress = gtk.ProgressBar()
        self._action = gtk.Label()
        self._cancel = gtk.Button()
        self._cancel.set_label('Cancel')
        self._dialog.vbox.pack_start(self._action)
        self._dialog.vbox.pack_start(self._progress)
        self._dialog.action_area.pack_start(self._cancel)
        threads_leave()
        
        def thread_target():
            self.poker_thread_routine()
        
        self._poked = False
        self._stopped = False
        self._poker_alarm = threading.Event()
        self._poker_thread = threading.Thread(target=thread_target)
        self._poker_thread.start()
        
    
    def show(self):
        threads_enter()
        self._dialog.show_all()
        threads_leave()
        
    def destroy(self):
        self._stop_poker_thread()

        done_event = threading.Event()
        
        def do_remove():
            threads_enter()
            self._dialog.destroy()
            threads_leave() 
            done_event.set()
        
        gobject.idle_add(do_remove)
        done_event.wait()
        
    def _stop_poker_thread(self):
        self._stopped = True
        self._poker_alarm.set()
        
    def set_indeterminate(self):
        if not self._poked:
            self._poked = True
            self._poker_alarm.set()
        
    def poker_thread_routine(self):
        
        while True:
            
            # check if we've been killed
            if self._stopped:
                return
            
            if self._poked:
                self._poker_alarm.wait(0.5)
            else:
                self._poker_alarm.wait()

            self._poker_alarm.clear()
            self.queue_a_pulse()
            
    def queue_a_pulse(self):
        
        def do_pulse(self):
            threads_enter()
            self._progress.pulse()
            threads_leave()
        
        gobject.idle_add(do_pulse, self)
        
    def set_activity(self, text):
        self._poked = False
        threads_enter()
        self._action.set_text(text)
        self._progress.set_fraction(0)
        self._dialog.resize_children()
        threads_leave()
        
    def update_progress(self, progress):
        value = float(progress) / 100

        if value < 0:
            value = 0
        if value > 1:
            value = 1
        
        threads_enter()
        self._progress.set_fraction(value)
        threads_leave()
        
def ask_retry_device(allow_later):
    
    event = threading.Event()

    def callback(dialog, response_id, response_holder):
        global response
        response = response_id
        response_holder['value'] = response_id
        # let the calling thread know we are done
        event.set()
        
    def show_dialog(response_holder):
        threads_enter()
        dialog = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION,
                                   message_format="Couldn't connect to media player.",
                                   buttons=gtk.BUTTONS_NONE)
    
        dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,\
                           gtk.STOCK_OK, gtk.RESPONSE_OK)
        
        if allow_later:
            dialog.add_buttons("Connect Later", 42)
            
        dialog.format_secondary_text("Make sure your device is connected and turned on.  Do you want to try to connect again?")
        dialog.connect('response', callback, response_holder)
        response = dialog.show()
        response_holder['dialog'] = dialog
        
        threads_leave()
        
    def remove_dialog(response_holder):
        threads_enter()
        response_holder['dialog'].destroy()
        threads_leave()
        
    # pass around an object, rather than a global
    response_holder = {}

    # get the gtk thread to do the gui stuff, because it is deadlocking
    # with just getting the gtk lock
    gobject.idle_add(show_dialog, response_holder)
    
    # the gtk thread will wake us up once gui has been acknowledged
    event.wait()
    
    response = response_holder['value']

    # get gtk to ditch the dialog when it is ready
    gobject.idle_add(remove_dialog, response_holder)    
    
    if response == gtk.RESPONSE_OK:
        return RETRY_OK
    elif response == 42:
        return RETRY_LATER
    
    return RETRY_CANCEL
        
def show_error(error_object):
    
    threads_enter()
    dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
                               buttons=gtk.BUTTONS_OK,
                               message_format='Error Encoding Video')

    err_string = str(error_object)
    
    if len(err_string) > 200:
        err_string = err_string[:200]

    dialog.format_secondary_markup('Your video couldn\'t be encoded because of an error ' +
                                'running the <i>mencoder</i> encoding program.\n\n<b>Error message</b>\n' + 
                                '<tt>%s</tt>' % err_string)
    dialog.run()
    threads_leave()

    # destroy later - avoids a weird deadlock problem
    gobject.idle_add(dialog.destroy)
    
        
if __name__ == '__main__':
    gtk.gdk.threads_init()
    monitor = EncoderProgressMonitor()
    monitor.show()
    gtk.main()